<template>
  <van-uploader
    v-model="fileList"
    multiple
    :max-count="6"
    :before-read="beforeRead"
    :after-read="afterRead"
    :preview-options="{closeable:'true'}"
    @delete="deleteFile"
    @oversize="onOversize"
  />
  <canvas
    id="waterMarkCanvas"
    v-if="waterMarkCanvas.display"
    :width="waterMarkCanvas.canvasWidth"
    :height="waterMarkCanvas.canvasHeight"
    style="position: fixed; left: 9999px"
  ></canvas>
</template>

<script>
import { formatDay, formatTime, formatWeek, isArray } from '@/utils'
import { reactive, onMounted, toRefs, nextTick } from 'vue'
import { getAssetsImages } from '@/utils'
import AMap from '@/utils/maps/maps'
export default {
  name: 'WaterMarkUploader',
  emits: ['afterRead', 'beforeRead','deleteFile'],
  props: {
    files: {
      type: Array,
      default: () => []
    }
  },
  setup(props, cxt) {
    const state = reactive({
      waterMarkCanvas: {
        display: false, // 控制 canvas 创建与销毁
        canvasWidth: 300, // 默认宽度
        canvasHeight: 225, // 默认高度
        contentHeight: 390 // 将要被绘制到图像中的矩形的高度(px)
      },
      originWidth: 882,
      waterMarkParams: {
        spacing: 30, // 距离图片边的边距
        fontSize: 32, // 基础字体大小
        lineHeight: 44, // 字体大概高度+行距16
        codeWidth: 200, //二维码宽度
        codeHeight: 200, //二维码高度
        rectWidth: 4, //细矩形宽度
        rectHeight: 50, //细矩形高度
        logoWidth: 100, //logo宽度
        logoHeight: 66 //logo高度
      },
      waterMarkInfo: {},
      fileList: props.files
    })
    const onOversize = (file) => {
      console.log(file)
      Toast('图片大小不能超过 2MB')
    }
    // 添加水印
    const addWaterMark = (src) => {
      return new Promise((resolve, reject) => {
        // 获取图片信息，配置 canvas 尺寸
        var img = new Image()
        img.onload = function () {
          const width = img.width // 获取图片的原始宽度
          const height = img.height // 获取图片的原始高度
          console.log(`图片的原始尺寸为：${width} x ${height}`)
          const res = { width, height }
          // 修复部分手机(如红米9)手机屏幕比较窄拍摄出来的图片水印压缩着覆盖的问题
          state.waterMarkCanvas.display = true
          state.waterMarkCanvas.canvasWidth = state.originWidth
          state.waterMarkCanvas.canvasHeight = res.height * (state.originWidth / res.width)

          console.log('当前图片信息waterMarkCanvas：', state.waterMarkCanvas)
          // 等待 canvas 元素创建
          nextTick(async () => {
            const canvas = document.getElementById('waterMarkCanvas')
            let context = canvas.getContext('2d')
            /* 绘制 */
            const { canvasWidth, canvasHeight, contentHeight } = state.waterMarkCanvas
            const {
              spacing,
              fontSize,
              lineHeight,
              codeWidth,
              codeHeight,
              rectWidth,
              rectHeight,
              logoWidth,
              logoHeight
            } = state.waterMarkParams

            // 绘制前清空画布
            context.clearRect(0, 0, canvasWidth, canvasHeight)
            // 将图片src放到cancas内，宽高必须为图片大小
            context.drawImage(img, 0, 0, canvasWidth, canvasHeight)
            // 设置边框的透明度
            context.globalAlpha = 0.4
            context.beginPath()
            // 绘制底部的白色背景
            context.rect(0, canvasHeight - contentHeight, canvasWidth, contentHeight)
            // context.rect(0, 0, canvasWidth, lineHeight + spacing * 2.5)
            context.fillStyle = '#000000'
            context.fill()
            // 设置文字的透明度
            context.globalAlpha = 1

            // 3.绘制底部的文字
            context.textAlign = 'left'
            context.fillStyle = 'white'
            context.font = `${fontSize}px Arial`
           
            // 底部的地址是否多行会影响其上面的位置
            const adressTextWidth = context.measureText(`${state.waterMarkInfo.address || ''}`).width
            const yAadressText =
              adressTextWidth > canvasWidth - codeWidth - spacing * 2
                ? canvasHeight - lineHeight * 2 - spacing * 2
                : canvasHeight - lineHeight - spacing * 2
            console.log(adressTextWidth, canvasWidth - codeWidth - spacing * 2, yAadressText)
            // 底部地址
            drawtext(
              context,
              `${state.waterMarkInfo.address || ''}`,
              spacing,
              yAadressText,
              canvasWidth - codeWidth - spacing * 2
            )

            // 时间
            context.font = `${fontSize * 1.8}px Arial`
            const timeTextWidth = context.measureText(`${state.waterMarkInfo.time}`).width
            context.fillText(`${state.waterMarkInfo.time}`, spacing, yAadressText - spacing*0.5)
            // 细矩形
            context.fillStyle = '#e9c232'
            context.fillRect(
              (timeTextWidth + spacing * 2).toFixed(),
              yAadressText - spacing*0.3 - rectHeight,
              rectWidth,
              rectHeight
            )
            context.fillStyle = 'white'
            // 日期
            context.font = `${fontSize}px Arial`
            context.fillText(
              `${state.waterMarkInfo.day}`,
              (timeTextWidth + spacing * 3).toFixed(),
              yAadressText - spacing * 0.8
            )
            // 周几
            context.fillText(
              `${state.waterMarkInfo.week}`,
              (timeTextWidth + spacing * 9).toFixed(),
              yAadressText - spacing * 0.8
            )
            // 公司-部门-维修员名称
            context.font = `${fontSize*0.9}px Arial`
            drawtext(
              context,
              `${state.waterMarkInfo.tenantName}${state.waterMarkInfo.dept_name?' - ':''}${state.waterMarkInfo.dept_name}${state.waterMarkInfo.real_name?' - ':''}${state.waterMarkInfo.real_name}`,
              spacing,
              yAadressText -
									spacing * 2.5 -
									fontSize * 2 ,
              canvasWidth - spacing
            )
            // 绘制logo
            if (state.waterMarkInfo.tenantLogoUrl) {
              // const tenantLogoUrl = await loadAllImages(['http://shanzuwang-test.oss-cn-shanghai.aliyuncs.com/upload/20241121/a1914c700b4475f06b772131e682ddc9.jpg'])
              const tenantLogoUrl = await loadAllImages([state.waterMarkInfo.tenantLogoUrl])

              // const tenantLogoUrl = await loadAllImages([getAssetsImages('logo.jpg')])
              const {width, height} = tenantLogoUrl[0]
              context.drawImage(
                tenantLogoUrl[0],
                spacing,
                yAadressText - spacing * 2.5 - fontSize * 2 - logoHeight,
                Math.ceil((width*logoHeight)/height),
                logoHeight
              )
            }
            // 绘制二维码
            if (state.waterMarkInfo.qrCode) {
              context.drawImage(
                state.waterMarkInfo.qrCode,
                canvasWidth - codeWidth - spacing,
                yAadressText - spacing - fontSize * 2 - logoHeight,
                codeWidth,
                codeHeight
              )
            }
            // 本次绘画完重开开始绘画，并且在绘画完毕之后再保存图片，不然页面可能会出现白屏等情况
            // 一定要加上一个定时器否则进入到页面第一次可能会无法正常拍照，后几次才正常
            setTimeout(() => {
              const fileContent = canvas.toDataURL('image/jpeg')
              resolve(fileContent)
            }, 1000)
          })
        }
        img.src = src
      })
    }
    // 获取水印部分内容
    const getWaterMarkInfo = async () => {
      state.waterMarkInfo = {
        ...state.waterMarkInfo,
        ...state.waterMark
      }
      // 获取当前日期、时间、周
      let newDate = new Date()
      state.waterMarkInfo.day = formatDay(newDate)
      state.waterMarkInfo.time = formatTime(newDate, false)
      state.waterMarkInfo.week = formatWeek(newDate)
      if (localStorage.getItem('userInfo')) {
        const { realName, deptName } = JSON.parse(localStorage.getItem('userInfo'))
        state.waterMarkInfo.real_name = realName || ''
        state.waterMarkInfo.dept_name = deptName || ''
      }
      const tenantInfo = JSON.parse(localStorage.getItem('tenantInfo'))
      state.waterMarkInfo.tenantName = tenantInfo.tenantName;
      state.waterMarkInfo.tenantLogoUrl = tenantInfo.tenantLogoUrl;
    }
    const getLocationInfo = () => {
      AMap().then(() => {
        const geolocation = new window.AMap.Geolocation({
          enableHighAccuracy: true, // 是否使用高精度定位，默认:true
          timeout: 60000, // 超过10秒后停止定位，默认：5s
          position: 'RB', // 定位按钮的停靠位置
          buttonOffset: new window.AMap.Pixel(10, 20), // 定位按钮与设置的停靠位置的偏移量，默认：Pixel(10, 20)
          zoomToAccuracy: true // 定位成功后是否自动调整地图视野到定位点
        })
        geolocation.getCurrentPosition(function (status, result) {
          state.waterMarkInfo.address = result.formattedAddress;
          // state.longitude = result.position.lng;
          // state.latitude =  result.position.lat;
          // result.formattedAddress  完整地址
          // alert('高德定位' + status + JSON.stringify(result))
        })
      })
    }
    // 文本换行
    const drawtext = (ctx, t, x, y, w) => {
      //参数说明
      //ctx：canvas的 2d 对象，t：绘制的文字，x,y:文字坐标，w：文字最大宽度
      let chr = t.split('')
      let temp = ''
      let row = []

      for (let a = 0; a < chr.length; a++) {
        if (ctx.measureText(temp).width < w && ctx.measureText(temp + chr[a]).width <= w) {
          temp += chr[a]
        } else {
          row.push(temp)
          temp = chr[a]
        }
      }
      row.push(temp)
      for (let b = 0; b < row.length; b++) {
        ctx.fillText(row[b], x, y + (b + 1) * state.waterMarkParams.lineHeight) //每行字体y坐标间隔24+8-就是行间距
      }
    }
    const beforeRead = () => {
      // 若定位信息未拿到，提示
      // if()
      cxt.emit('beforeRead')
      return true
    }
    const afterRead = async (file) => {
      // 此时可以自行将文件上传至服务器
      console.log('afterRead', file)

      if (isArray(file)) {
        for (let i = 0; i < file.length; i++) {
         await singleToAdd(file[i])
        }
      } else {
        singleToAdd(file)
      }
    }
    // 单个图片添加水印
    const singleToAdd = (file) => {
      return new Promise(async (resolve, reject) => {
        const path = await addWaterMark(file.content)
        let blob = dataURLtoBlob(path)
        // 拿到文件名
        let fileName = file.file.name
        // 2，在转为 file类型
        let newFile = blobToFile(blob, fileName)
        file.file = newFile
        file.content = path
        cxt.emit('afterRead', file)
        resolve()
      })
    }
    const deleteFile = (file, indexData) => {
      cxt.emit('deleteFile', indexData)
    }
    // 包装获取网络图片
    const loadAllImages = (imgUrls) => {
      const _load = function (imgUrl) {
        //创建img标签
        let loadimg = new Image()
        loadimg.src = imgUrl
        //跨域选项
        loadimg.setAttribute('crossOrigin', 'Anonymous')
        return new Promise((resolve, reject) => {
          //文件加载完毕
          loadimg.onload = function () {
            resolve(loadimg)
          }
        })
      }
      const _loadAll = function (imgUrls) {
        const loadedImageUrls = []
        for (let i = 0, len = imgUrls.length; i < len; i++) {
          loadedImageUrls.push(_load(imgUrls[i]))
        }
        return loadedImageUrls
      }
      return Promise.all(_loadAll(imgUrls))
    }
    const dataURLtoBlob = (dataurl) => {
      var arr = dataurl.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      return new Blob([u8arr], { type: mime })
    }
    //2,再将blob转换为file
    const blobToFile = (theBlob, fileName) => {
      theBlob.lastModifiedDate = new Date() // 文件最后的修改日期
      theBlob.name = fileName // 文件名
      return new File([theBlob], fileName, { type: theBlob.type, lastModified: Date.now() })
    }
    onMounted(() => {
      // 获取水印部分内容
      getWaterMarkInfo()
      getLocationInfo()
    })
    return {
      ...toRefs(state),
      beforeRead,
      afterRead,
      deleteFile,
      onOversize
    }
  }
}
</script>

<style lang="less" scoped>
.card {
  background: #fff;
  padding: 10px;
  box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.05);
  border-radius: 4px;
  overflow: hidden;
}
</style>
